package com.distribute.framework.core.lang;

import com.distribute.framework.core.web.helper.Utils;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;


import com.distribute.framework.core.web.helper.WebHelper.LzMap;

public class Feflect {
	
	public static void main(String...strings) throws Exception{
		LzMap map = Utils.add("aaa", 4);
		final List list = new ArrayList();
		list.add(Utils.add("aaa", 4));
		list.add(Utils.add("aaa", 5));
		Utils.trace(getFieldValue(new Object(){
			public List bbb = list;
			public List getBbb() {
				return bbb;
			}
			public void setBbb(List bbb) {
				this.bbb = bbb;
			}
		},"bbb[2].aaa"));
	}

	/**
	 * 获取对象字段值 
	 * @param object 对象
	 * @param fieldExpression 字段表达式
	 * @return
	 * @throws Exception
	 */
	public static String getFieldValue(Object object, String fieldExpression) throws Exception {
		String[] array = fieldExpression.split("\\.");
		
		String arrayRegx = "\\[([0-9]+)?\\]";
		
		for(int i=0;i<array.length-1;i++){
			String fieldName = array[i].replaceAll(arrayRegx, "");
			Field field = getClassField(object.getClass(),fieldName);
			relate relate = field.getAnnotation(relate.class);
			Method getMethod = object.getClass().getMethod("get"+ForMat(relate!=null ? relate.value() : fieldName));
			object = getMethod.invoke(object);
			if(object==null)
				return "";
			Matcher m = java.util.regex.Pattern.compile(arrayRegx).matcher(array[i]);
			if(m.find()){
				int index = 0;
				if(m.groupCount()>0 && !Utils.empty(m.group(1)))
					index = Integer.parseInt(m.group(1));	
				if(((List)object).size()>index)
					object = ((List)object).get(index);
				else
					return "";
			}
		}
		
		if(object instanceof Map){
			Map map = (Map) object;
			return Utils.str(map.get(array[array.length-1]));
		}else{
			Method getMethod$ = getClassMethod(object.getClass(),"get"+ForMat(array[array.length-1])+"$");
			if(getMethod$!=null)
				return Utils.str(getMethod$.invoke(object));
			Method getMethod = getClassMethod(object.getClass(),"get"+ForMat(array[array.length-1]));
			if(getMethod!=null)
				return Utils.str(getMethod.invoke(object));
			Field field = getClassField(object.getClass(),array[array.length-1]);
			if(field!=null){
				field.setAccessible(true);
				return Utils.str(field.get(object));
			}
		}
		return "";
	}

	/**
	 * 根据类和字段表达式取字段描述
	 * @param rootClass
	 * @param fieldExpression 字段以 . 分隔
	 * @return
	 * @throws NoSuchFieldException 
	 * @throws SecurityException 
	 */
	public static String getFieldCaption(Class rootClass, String fieldExpression) throws Exception {
		fieldExpression = fieldExpression.replace("[]", "");
		String[] array = fieldExpression.split("\\.");
		Class cls = rootClass;
		for(int i=0;i<array.length-1;i++){
			String fieldName = array[i];
			Field field = getClassField(cls,fieldName);
			field.setAccessible(true);
			RelateClass relateClass = field.getAnnotation(RelateClass.class);
			cls = relateClass==null?null:relateClass.value();
			if(cls==null){
				relate relate = field.getAnnotation(relate.class);
				cls =  getClassField(cls,relate!=null ? relate.value() : fieldName).getType();
			}
		}
		Field field = getClassField(cls,array[array.length-1]);
		if(field==null){
			new Exception("类"+cls.getName()+"找不到"+array[array.length-1]+"字段").printStackTrace();
			return "null";
		}
		caption caption = field.getAnnotation(caption.class);
		if(caption==null)
			throw new Exception("类"+cls.getName()+"的"+array[array.length-1]+"字段未注解字体描述@caption");
		return caption.value();
	}
	
	
	/**
	 * 获取类的字段信息
	 * @param className 类名
	 * @param fieldExpression 字段表达式
	 * @return
	 * @throws Exception
	 */
	public static ClassField getField(Class cls, String fieldExpression) throws Exception {
		try{
			fieldExpression = fieldExpression.replace("[]", "");
			String[] array = fieldExpression.split("\\.");
			for(int i=0;i<array.length-1;i++){
				String fieldName = array[i];
				Field field = getClassField(cls,fieldName);
				RelateClass relateClass = field.getAnnotation(RelateClass.class);
				cls = relateClass==null?null:relateClass.value();
				if(cls==null){
					relate relate = field.getAnnotation(relate.class);
					cls =  getClassField(cls,relate!=null ? relate.value() : fieldName).getType();
				}
			}
			Field field = getClassField(cls,array[array.length-1]);
			if(field==null)
				return null;		
			ClassField classField = new ClassField();
			classField.setName(field.getName());
			classField.setType(field.getType());
			for(Annotation annotation:field.getAnnotations()){
				classField.addNote(annotation);
			}
			return classField;
		}catch(Exception ex){
			ex.printStackTrace();
		}
		return null;
	}
			
	
	protected static String forMat(String string){
		if(string==null || string.equals(""))
			return string;
		return string.substring(0,1).toLowerCase() + string.substring(1);
	}
	protected static String ForMat(String string){
		if(string==null || string.equals(""))
			return string;
		return string.substring(0,1).toUpperCase() + string.substring(1);
	}
	protected static Method getClassMethod(Class cls,String methodName){
		Method method = null;
		try {
			method = cls.getMethod(methodName);
		} catch (Exception e) {	}
		return method;
	}
	protected static Field getClassField(Class cls,String fieldName){
		Field field = null;
		try{
			field = cls.getDeclaredField(fieldName.replace("[]", ""));
		} catch (Exception e) { }
		return field;
	}
	
	
}